package com.ctg.itrdc.imageconsole.service.deploy;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;

import javax.annotation.Resource;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.commons.lang3.StringUtils;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.springframework.stereotype.Component;

import com.ctg.itrdc.imageconsole.common.util.PropertiesUtils;
import com.ctg.itrdc.imageconsole.common.util.TimeUtils;
import com.ctg.itrdc.imageconsole.data.dao.IAutoscalePolicyDao;
import com.ctg.itrdc.imageconsole.data.dao.IClusterConfigDao;
import com.ctg.itrdc.imageconsole.data.dao.IDockerImageDao;
import com.ctg.itrdc.imageconsole.data.dao.IDockerImageTagDao;
import com.ctg.itrdc.imageconsole.data.dao.IDockerMicroAppDao;
import com.ctg.itrdc.imageconsole.data.dao.IDockerMicroGroupDao;
import com.ctg.itrdc.imageconsole.data.dao.IDockerMicroGroupDetailDao;
import com.ctg.itrdc.imageconsole.data.dao.IDockerMicroImageDao;
import com.ctg.itrdc.imageconsole.data.dao.IDockerMicroServiceDao;
import com.ctg.itrdc.imageconsole.data.dao.ISystemNoticeDao;
import com.ctg.itrdc.imageconsole.data.dto.DmsAppDTO;
import com.ctg.itrdc.imageconsole.data.dto.DmsAppReturnDTO;
import com.ctg.itrdc.imageconsole.data.dto.DmsServiceReturnDTO;
import com.ctg.itrdc.imageconsole.data.entity.AutoscalePolicy;
import com.ctg.itrdc.imageconsole.data.entity.ClusterConfig;
import com.ctg.itrdc.imageconsole.data.entity.DockerMicroApp;
import com.ctg.itrdc.imageconsole.data.entity.DockerMicroService;
import com.ctg.itrdc.imageconsole.util.KubeUtils;
import com.ctg.itrdc.imageconsole.util.SysManagerUtil;
import com.ctg.itrdc.k8sconsole.service.IK8snodeService;
import com.ctg.itrdc.pasp.security.utils.WebUtils;
import com.ctg.itrdc.paspsdk.common.entity.PageInfo;
import com.ctg.itrdc.paspsdk.data.dao.IBaseDao;

@Component("appManageServiceAux")
public class AppManagerServiceAux {


	@Resource
	IBaseDao baseDao;
	
	@Resource
	IDockerMicroAppDao appDao;
	
	@Resource
	IDockerMicroServiceDao serviceDao;
	
	@Resource
	IAutoscalePolicyDao autoscalePolicyDao;
	
	@Resource
	IDockerMicroImageDao microImageDao;
	
	@Resource
	IDockerImageTagDao imageIndexDao;
	@Resource
	IDockerImageDao imageFileDao;
	@Resource
	IClusterConfigDao clusterConfigDao;
	@Resource
	IDockerMicroGroupDao groupDao;
	@Resource
	IDockerMicroGroupDetailDao groupDetailDao;
	@Resource
	IK8snodeService k8sNodeService;
	@Resource
	ISystemNoticeDao noticeDao;
	
	
	public PageInfo<DmsAppReturnDTO> getAppDTOList(String appCode, Integer pageNum, Integer pageSize) 
	{		
		Long userId = WebUtils.getCtgUser().getSysUserId();
		String sql = "select dma.id as appId, dma.code as appCode, dma.name as appName, dma.create_time as createTime," +
				" dma.description as description, dma.k8s_code as k8sCode, dma.namespace as namespace, dmu.code as create_user_code" + 			
				" from docker_micro_app dma, docker_micro_user dmu where dma.create_user_id = dmu.sys_user_id ";		
		
		List<Object> params = new ArrayList<>();
		StringBuilder sb = new StringBuilder(sql);
		
		if (!SysManagerUtil.isRoleOfDockerManager()) {
			sb.append(" and dma.create_user_id = ?");
			params.add(userId);		
		}
		if (StringUtils.isNotEmpty(appCode)) {
			sb.append(" and dma.code like ?");
			params.add("%" + appCode + "%");
		}
		sb.append(" order by dma.create_time desc");
		PageInfo<DmsAppReturnDTO> pageInfo = baseDao.jdbcFindPageInfo(sb.toString(), DmsAppReturnDTO.class, params, pageNum, pageSize);
		
		return pageInfo;
	}		
	
	 
	public DmsAppReturnDTO getAppDTO(Long appId) 
	{		
		Long userId = WebUtils.getCtgUser().getSysUserId();
		DockerMicroApp app = new DockerMicroApp();
		app.setId(appId);
		app.setCreateUserId(userId);
		app = appDao.selectByPrimaryKey(app);
		DmsAppReturnDTO appReturnDTO = new DmsAppReturnDTO();
		appReturnDTO.setAppId(app.getId());
		appReturnDTO.setAppCode(app.getCode());
		appReturnDTO.setAppName(app.getName());
		appReturnDTO.setDescription(app.getDescription());
		appReturnDTO.setK8sCode(app.getK8sCode());
		appReturnDTO.setNamespace(app.getNamespace());
		appReturnDTO.setCreateTime(app.getCreateTime());
		return appReturnDTO;
	}
	

	
	public Object getVersions(Long serviceId)
	{		
		DockerMicroService service = serviceDao.selectById(serviceId);
		if(null == serviceId)
			throw new RuntimeException("Error : selecting docker_micro_service by id returns null");
		String apiServerUrl = clusterConfigDao.selectApiServerUrlByClusterCode(service.getK8sCode());
		return KubeUtils.getRssByDp(apiServerUrl, service.getNamespace(), service.getDpName());	
	}
	
	
	public PageInfo<DmsServiceReturnDTO> getServices(Long appId, Integer pageNum, Integer pageSize) {
		String sql = "select service.id as serviceId, service.code as serviceCode, service.dp_name as dpName," +
					" service.url as url, service.external_port as externalPort, service.lvs_service_name as lvsServiceName, service.yaml_content as yamlContent," +
					" service.is_autoscalable as isAutoscalable, service.autoscale_policy_id as autoscalePolicyId," +
					" service.k8s_code as k8sCode, service.namespace as namespace, service.state as state," +
					" service.release_state as releaseState, service.release_state_description as releaseStateDescription," +
					" autoscale_policy.elastic_indicator as elasticIndicator, autoscale_policy.min_pod_num as minPodNum," +
					" autoscale_policy.max_pod_num as maxPodNum, autoscale_policy.max_cpu as maxCpu," +
					" autoscale_policy.elastic_start_time as elasticStartTime, autoscale_policy.elastic_end_time as elasticEndTime," +
					" autoscale_policy.time_rate as timeRate" +
					" from (select * from docker_micro_service where docker_micro_service.docker_micro_app_id = ?) as service" +
					" left join autoscale_policy" +
					" on service.autoscale_policy_id = autoscale_policy.id";
		List<Object> params = new ArrayList<>();
		params.add(appId);
		return baseDao.jdbcFindPageInfo(sql, DmsServiceReturnDTO.class, params, pageNum, pageSize);
	}
	
	public DmsServiceReturnDTO getService(Long serviceId) {
		DockerMicroService service = serviceDao.selectById(serviceId);
		DmsServiceReturnDTO serviceReturnDTO = new DmsServiceReturnDTO();
		serviceReturnDTO.setServiceId(serviceId);
		serviceReturnDTO.setServiceCode(service.getCode());		
		serviceReturnDTO.setDpName(service.getDpName());		
		serviceReturnDTO.setUrl(service.getUrl());
		serviceReturnDTO.setExternalPort(service.getExternalPort());
		serviceReturnDTO.setLvsServiceName(service.getLvsServiceName());
		serviceReturnDTO.setYamlContent(service.getYamlContent());
		serviceReturnDTO.setIsAutoScalable(service.getIsAutoscalable());
		serviceReturnDTO.setAutoscalePolicyId(service.getAutoscalePolicyId());
		serviceReturnDTO.setK8sCode(service.getK8sCode());
		serviceReturnDTO.setNamespace(service.getNamespace());
		serviceReturnDTO.setState(service.getState());
		serviceReturnDTO.setReleaseState(service.getReleaseState());
		serviceReturnDTO.setReleaseStateDescription(service.getReleaseStateDescription());
		
		if(1 == service.getIsAutoscalable().intValue()) {	
			AutoscalePolicy autoscalePolicy = autoscalePolicyDao.selectById(service.getAutoscalePolicyId());
			serviceReturnDTO.setElasticIndicator(autoscalePolicy.getElasticIndicator());
			serviceReturnDTO.setMinPodNum(autoscalePolicy.getMinPodNum());
			serviceReturnDTO.setMaxPodNum(autoscalePolicy.getMaxPodNum());
			serviceReturnDTO.setMaxCpu(autoscalePolicy.getMaxCpu());
			serviceReturnDTO.setElasticStartTime(autoscalePolicy.getElasticStartTime());
			serviceReturnDTO.setElasticEndTime(autoscalePolicy.getElasticEndTime());
			serviceReturnDTO.setTimeRate(autoscalePolicy.getTimeRate());
		}	
		
		return serviceReturnDTO;
	}
	
	public void deployAux(Long serviceId)
	{	
		final DockerMicroService service = serviceDao.selectById(serviceId);
		if(null == service)
			throw new RuntimeException("Error : selecting docker_micro_service by id returns null");
		String apiServerUrl = clusterConfigDao.selectApiServerUrlByClusterCode(service.getK8sCode());
		if(null == apiServerUrl)
			throw new RuntimeException("Error : selecting api_server_url by cluster_code returns null");
		try
		{		
			KubeUtils.createDp(apiServerUrl, service.getNamespace(), service.getYamlContent());				
			serviceDao.updateStateAndReleaseStateAndDesc(serviceId, "001", "002", "deploy success", TimeUtils.getNowDateStr());
		} catch(Exception e) {			
			serviceDao.updateStateAndReleaseStateAndDesc(serviceId, "002", "003", e.getMessage(), TimeUtils.getNowDateStr());				
			throw new RuntimeException(e.getMessage());
		}
		
		/*
		if(service.getIsAutoScalable().intValue() != 0)		// start autoElastic job			
		{				
			try
			{
				autoElasticService.startAutoElastic(version);
			} catch(Exception e) {
				logger.error(e.getMessage());
			}
		}	
		*/
	}	

	

	public void updateAppDescription(DmsAppDTO appDTO)
	{	
		DockerMicroApp app = new DockerMicroApp();
		app.setId(appDTO.getAppId());
		app.setDescription(appDTO.getDescription());
		app.setLastUpdateUserId(WebUtils.getCtgUser().getSysUserId());
		app.setLastUpdateTime(TimeUtils.getNowDateStr());
		appDao.updateSelectiveByPrimaryKey(app);
	}
	
/*
	public void healthCheckAux(DockerMicroManageDetail detail) 
	{
		String apiServerUrl = clusterConfigDao.selectApiServerUrlByClusterCode(detail.getK8sCode());
		String rcName = detail.getRcName();
		if("003".equals(detail.getState()))
			return;
		if(KubeUtils.rcExist(apiServerUrl, rcName))
		{			
			if(!("001".equals(detail.getState()) && "002".equals(detail.getReleaseState())))
				manageDetailDao.updateStateAndReleaseStateAndDesc(detail.getId(), "001", "002", 
					"rc exists while db is tagged offline, db updated to online", 0L, TimeUtils.getNowDateStr());
		}			
		else if("002".equals(detail.getState()) && "001".equals(detail.getReleaseState()))
			manageDetailDao.updateStateAndReleaseStateAndDesc(detail.getId(), "002", "003", 
				"Deploying takes too long, and db updated to false state", 0L, TimeUtils.getNowDateStr());			
	}	
	
	*/	 
	
	public void callLvs(String k8sCode, String url, String externalPort, String lvsServiceName) 
	{	
		ClusterConfig clusterConfig = clusterConfigDao.queryByClusterCode(k8sCode);
		String distributedWebAddress = PropertiesUtils.getConfigValueCache("config.properties", "distributedWeb.address");
		if(null ==distributedWebAddress)
			throw new RuntimeException(String.format("%s is not configured in %", "distributedWeb.address", "config.properties"));
		distributedWebAddress = MessageFormat.format(distributedWebAddress, clusterConfig.getDistributedWebUrl(), clusterConfig.getTengineClusterCode());
		
		TreeMap<String, String> parasMap = new TreeMap<String, String>();
		parasMap.put("address", url);
		parasMap.put("port", externalPort);
		parasMap.put("app_name", lvsServiceName);
		WebTarget target = new ResteasyClientBuilder().build().target(distributedWebAddress);		
		Response response = target.request().post(Entity.entity(parasMap, MediaType.APPLICATION_JSON_TYPE));
		if(response.getStatus() >= 300)
		{
			throw new RuntimeException("Error : calling lvs : " + response.getStatus() + " " + response.getEntity().toString());
		}
	}

}
